﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Xml.XPath;

namespace Zen4SyncPOCO.ClientTestSessionDescriptorHandler
{
    internal static class XmlTools
    {
        /// <summary>
        /// Returns the "best value" for the given xpath.
        /// The best value is the one found when evaluating the given xpath on the bestValueNode.
        /// If the given xpath does not match any node on the bestValueNode, then it's evaluated against defaultValueNode
        /// and the value is returned.
        /// </summary>
        /// <param name="bestValueNode">The node on which xpath will be evaluated first.</param>
        /// <param name="defaultValueNode">The node on which xpath will be evaluated if there's no match on bestValueNode.</param>
        /// <param name="xpath">The xpath to evaluate on nodes.</param>
        /// <returns>
        /// The value corresponding to the xpath evaluated on bestValueNode.
        /// If there is no match on bestValueNode, then returns the value of the xpath evaluated on defaultValueNode.
        /// </returns>
        internal static string GetBestValue(XElement bestValueNode, string xpath, XElement defaultValueNode)
        {
            if (xpath.Contains("@"))
            {
                string[] xpathDetails = xpath.Split('@');
                string noAttributeXpath = xpathDetails[0].TrimEnd('/');
                string attribute = xpathDetails[1];
                
                XElement finalNodeOnBestNode = null;
                XElement finalNodeOnDefaultNode = null;

                if (bestValueNode != null)
                {
                    finalNodeOnBestNode = bestValueNode.XPathSelectElement(noAttributeXpath);
                }

                if (defaultValueNode != null)
                {
                    finalNodeOnDefaultNode = defaultValueNode.XPathSelectElement(noAttributeXpath);
                }

                if (finalNodeOnBestNode != null && finalNodeOnBestNode.Attribute(attribute) != null)
                {
                    return finalNodeOnBestNode.Attribute(attribute).Value;
                }

                if (finalNodeOnDefaultNode != null)
                {
                    return finalNodeOnDefaultNode.Attribute(attribute).Value;
                }
                
                return null;
            }

            if (bestValueNode != null && defaultValueNode != null)
            {
                return bestValueNode.XPathSelectElement(xpath) != null ? 
                        bestValueNode.XPathSelectElement(xpath).Value 
                        : defaultValueNode.XPathSelectElement(xpath).Value;
            }

            if (bestValueNode != null)
            {
                return bestValueNode.XPathSelectElement(xpath).Value;
            }

            if (defaultValueNode != null)
            {
                return defaultValueNode.XPathSelectElement(xpath).Value;
            }

            return null;
        }
    }
}
